﻿using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;

namespace Zeus.Results
{
    public class ZFileResult : IHttpActionResult
    {

        private IZFileResultFormatter _zFileResultFormatter;
        public ZFileResult(IZFileResultFormatter zFileResultFormatter)
        {
            _zFileResultFormatter = zFileResultFormatter;
        }

        public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            return await Execute(cancellationToken);
        }

        private async Task<HttpResponseMessage> Execute(CancellationToken cancellationToken)
        {
            var response = new HttpResponseMessage(HttpStatusCode.OK);
            var segment = await Serialize(cancellationToken);
            response.Content = new ByteArrayContent(segment.Array, segment.Offset, segment.Count);
            response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue($"attachment");
            response.Content.Headers.ContentDisposition.FileName = _zFileResultFormatter.FileName;
            return response;
        }

        private async Task<ArraySegment<byte>> Serialize(CancellationToken cancellationToken)
        {
            var buffer = new ArraySegment<byte>();
            if (_zFileResultFormatter.ByteBuffer != null && _zFileResultFormatter.ByteBuffer.Length > 0)
            {
                buffer = new ArraySegment<byte>(_zFileResultFormatter.ByteBuffer, 0, (int)_zFileResultFormatter.ByteBuffer.Length);
            }
            else if (_zFileResultFormatter.StreamBuffer != null && _zFileResultFormatter.StreamBuffer.Length > 0)
            {
                using (_zFileResultFormatter.StreamBuffer)
                {
                    _zFileResultFormatter.ByteBuffer = new byte[_zFileResultFormatter.StreamBuffer.Length];
                    await _zFileResultFormatter.StreamBuffer.ReadAsync(_zFileResultFormatter.ByteBuffer, 0, _zFileResultFormatter.ByteBuffer.Length, cancellationToken);
                    buffer = new ArraySegment<byte>(_zFileResultFormatter.ByteBuffer, 0, (int)_zFileResultFormatter.ByteBuffer.Length);
                    _zFileResultFormatter.StreamBuffer.Close();
                }
            }
            await _zFileResultFormatter.OnSerialize(buffer);
            return buffer;
        }
    }
}
